package org.oreilly.javaGoodParts.examples;

import org.junit.Test;

import java.util.Collection;
import java.util.Map;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

public class SmokeTest {

	@Test
	public void test() {

		final Team red = new Team("Red");
		Player ron = new Player("Ron");
		Player rick = new Player("Rick");
		final Team blue = new Team("Blue");
		Player bob = new Player("Bob");

		Collection<Event> events = Lists.newArrayList();
		events.add(new BattingEvent(red, ron, BattingEvent.Result.STRIKE_OUT));
		events.add(new BattingEvent(red, ron, BattingEvent.Result.STRIKE_OUT));
		events.add(new BattingEvent(red, ron, BattingEvent.Result.BASE_1));
		events.add(new BattingEvent(red, rick, BattingEvent.Result.BASE_1));
		events.add(new BattingEvent(blue, bob, BattingEvent.Result.STRIKE_OUT));
		events.add(new BattingEvent(blue, bob, BattingEvent.Result.BASE_4));

		events = Collections2.filter(events, new Predicate<Event>() {
			@Override
			public boolean apply(Event event) {
				return event.getTeam().equals(red);
			}
		});

		Map<Player, Float> result = mapReduce(events,
			new Function<Event, Player>() {
				@Override
				public Player apply(Event event) {
					return event.getPlayer();
				}
			},
			new Function<Iterable<Event>, Float>() {
				public Float apply(Iterable<Event> events) {
					return new BatterStats(events).getAverage();
				}
			}
		);

		println(new Leaderboard(result));
	}

	private static <I, K, V> Map<K, V> mapReduce(Iterable<I> input, Function<I, K> mapper, Function<Iterable<I>, V> reducer) {
		Map<K, V> output = Maps.newLinkedHashMap();
		Multimap<K, I> indexed = Multimaps.index(input, mapper);
		for (K key : indexed.keySet()) {
			output.put(key, reducer.apply(indexed.get(key)));
		}
		return output;
	}

	private static void println(Object value) {
		System.out.println(value);
	}
}
